////////////////////////////////////////////////////////////////////////////////
//
//  FLYING KIWI BV
//  Copyright 2010 Flying Kiwi BV
//  All Rights Reserved.
//
//  NOTICE: Flying Kiwi permits you to use, modify, and distribute this file
//  in accordance with the terms of the license agreement accompanying it.
//
////////////////////////////////////////////////////////////////////////////////
package plantool.data.sqlite {
	//--------------------------------------------------------------------------
	//  Imports
	//--------------------------------------------------------------------------
	import flash.data.SQLConnection;
	import flash.data.SQLResult;
	import flash.data.SQLStatement;
	import flash.errors.SQLError;
	import flash.events.SQLErrorEvent;
	import flash.events.SQLEvent;
	import flash.net.Responder;
	
	import kiwi.utils.Validation;
	
	import plantool.core.CoreObject;
	import plantool.data.QueryErrorResult;
	import plantool.data.QueryResult;
	
	//--------------------------------------------------------------------------
	//  [Metadata (Events, Style, Effects etc)]
	//--------------------------------------------------------------------------
	
	//--------------------------------------------------------------------------
	//  Class declaration
	//--------------------------------------------------------------------------
	public class SQLiteTransaction extends CoreObject {
		//--------------------------------------------------------------------------
		//Class constants
		//--------------------------------------------------------------------------
		
		//--------------------------------------------------------------------------
		//Class variables
		//--------------------------------------------------------------------------
		private var _statement:SQLStatement		= null;
		private var _onCompleteHandler:Function	= null;
		private var _onErrorHandler:Function	= null;
		private var _userdata:*					= null;
		private var _connection:SQLConnection	= null;
		private var _querys:Array				= null;
		private var _currentStatement:uint		= 0;
		
		//--------------------------------------------------------------------------
		//Class properties
		//--------------------------------------------------------------------------
		
		//--------------------------------------------------------------------------
		//Constructor and Destructor
		//--------------------------------------------------------------------------
		public function SQLiteTransaction(connection:SQLConnection, querys:Array, onCompleteHandler:Function, onErrorHandler:Function, itemClass:Class = null, userdata:* = null) {
			super();
			
			//store the complete and error handler
			_onCompleteHandler	= onCompleteHandler;
			_onErrorHandler		= onErrorHandler;
			_userdata			= userdata;

			//store connection and querys
			_connection = connection;
			_querys		= querys;

			//create savepoint and start transaction
			connection.setSavepoint("transaction_start", new Responder(onComplete_setSavepoint, onError_setSavepoint));
		}
		
		//--------------------------------------------------------------------------
		//Class methods
		//--------------------------------------------------------------------------
		private function executeStatement():void {
			//create current statement
			_statement 					= new SQLStatement();
			_statement.sqlConnection 	= _connection;
			_statement.text				= _querys[_currentStatement];
			
			//listen to result and error
			_statement.addEventListener(SQLEvent.RESULT			, onStatement_result);
			_statement.addEventListener(SQLErrorEvent.ERROR		, onStatement_error);
			
			//execute the statement
			_statement.execute();
		}
		
		private function onComplete_setSavepoint(e:SQLEvent):void {
			//execute statement
			executeStatement();
		}
		
		private function onComplete_rollback(result:SQLEvent):void {
			//create errorresult to return to caller
			var queryErrorResult:QueryErrorResult	= new QueryErrorResult(_statement.text, "Hours not saved, rolled back to before operation start");
			
			//call onerror handler
			if (Validation.isSet(_onErrorHandler)) {
				_onErrorHandler(queryErrorResult);
			}
		}
		
		private function onError_rollback(e:SQLErrorEvent):void {
			//create errorresult to return to caller
			var queryErrorResult:QueryErrorResult	= new QueryErrorResult(_statement.text, "Hours not saved, rollback also failed");
			
			//call onerror handler
			if (Validation.isSet(_onErrorHandler)) {
				_onErrorHandler(queryErrorResult);
			}
		}
		
		private function onError_setSavepoint(e:SQLErrorEvent):void {
			trace("error creating savepoint");
		}
		
		private function onSqlResult(result:SQLEvent):void {
			//get statement result
			var sqlResult:SQLResult 	= _statement.getResult();
			
			//create query-result to return to caller
			//TODO create accurate result for transaction
			var queryResult:QueryResult	= new QueryResult(null, "", 0, _userdata);
			
			//call oncomplete handler
			if (Validation.isSet(_onCompleteHandler)) {
				_onCompleteHandler(queryResult);
			}
		}
		
		private function onSqlError(result:SQLError):void {
			//rollback to previous savepoint
			_connection.rollbackToSavepoint("transaction_start", new Responder(onComplete_rollback, onError_rollback));
		}
		
		private function onStatement_error(e:SQLErrorEvent):void {
			//remove events from statement
			_statement.removeEventListener(SQLEvent.RESULT			, onStatement_result);
			_statement.removeEventListener(SQLErrorEvent.ERROR		, onStatement_error);
		}
		
		private function onStatement_result(e:SQLEvent):void {
			//remove events from statement
			_statement.removeEventListener(SQLEvent.RESULT			, onStatement_result);
			_statement.removeEventListener(SQLErrorEvent.ERROR		, onStatement_error);
			
			//increase statement #
			_currentStatement++;
			
			//check if all querys for the statement are complete
			if (_currentStatement == _querys.length) {
				//create a responder for the transaction
				var responder:Responder = new Responder(onSqlResult, onSqlError);
				
				//commit the changes
				_connection.releaseSavepoint("transaction_start", responder);
			} else {
				//execute the next statement
				executeStatement();
			}
		}
	}
}